public with sharing class RecordTypeHelper 
{
    private static Map<string, ID> recordTypes = new Map<string, ID>();
    private static Set<string> anticipatedObjectTypes; 
    
    // Helper Class - you can't instantiate
    private RecordTypeHelper(){}
     
     // PrepareToLoad - tags a object type. The object type's record types will be loaded the next time the salesforce database needs to be searched.
     // If you know (or are there is a good chance) that a particular object's recordtype IDs will be required you should call this method. 
     // You should call this method as early in the execution as possible 
    public static void PrepareToLoad(string objectType)
    {
        if(null == anticipatedObjectTypes)
            anticipatedObjectTypes = new Set<string>();
            
        anticipatedObjectTypes.add(objectType.toUpperCase());
    }

    // OBSOLETE!
    // GetRecordTypeId gets the record type ID for an object
    public static ID GetRecordTypeId(string objectType, string recordTypeName)
    {
        return GetRecordTypeId(objectType, recordTypeName, false, true);
    }

    // GetRecordTypeId gets the record type ID for an object
    public static ID GetRecordTypeIdByDevName(string objectType, string recordTypeDeveloperName)
    {
        return GetRecordTypeId(objectType, recordTypeDeveloperName, true, true);
    }
    
    private  static ID GetRecordTypeId(string objectType, string recordTypeName, boolean queryByDeveloperName, boolean queryIfNotFound)
    {
        string prefix = queryByDeveloperName ? 'D.' : 'N.';     
        string key = (prefix + objectType + '.' + recordTypeName).toUpperCase();
        ID recordTypeID = recordTypes.get(key);
        
        if(null == recordTypeID && queryIfNotFound)
        {
            PrepareToLoad(objectType);
            LoadRecordTypes();
            recordTypeID = GetRecordTypeId(objectType, recordTypeName, queryByDeveloperName, false);
        }       
        return recordTypeID;
    }
        
    private static void LoadRecordTypes()
    {
        System.assertNotEquals(null,anticipatedObjectTypes);
         
        for(RecordType rt : [select Id, Name, DeveloperName, SobjectType from RecordType where SobjectType in :anticipatedObjectTypes and IsActive =: true])
        {
            string nameKey = 'N.' + (rt.SobjectType + '.' + rt.Name).toUpperCase();
            recordTypes.put(nameKey, rt.Id);

            string developernamekey = 'D.' + (rt.SobjectType + '.' + rt.DeveloperName).toUpperCase();
            recordTypes.put(developernamekey, rt.Id);
        }
        anticipatedObjectTypes = null;                  
    }
      /**
     * This method validates wether the record type is not set. This can only happen when the user has only
     * rights to one specific record type. In that scenario the user does not see the record type selection screen.
     * In these cases the record type is not set out of the box. This method finds the appropiate record type for this user and 
     * add this as a parameter to the page.  
     */
    public static void SetRecordTypeIncaseNotSet(string ent) {
      System.Debug('selected record type ' + ApexPages.currentPage().getParameters().get('RecordType'));
        // in case it's null, the user has only one record type available. 
        if (ApexPages.currentPage().getParameters().get('RecordType') == null) {
        Schema.DescribeSObjectResult describeAccount ;
        if(ent=='Account')
            describeAccount = Schema.SObjectType.Account;
        else    
            describeAccount = Schema.SObjectType.Opportunity;
            
            List<Schema.RecordTypeInfo> rtInfos = describeAccount.getRecordTypeInfos();
            for(Schema.RecordTypeInfo rtInfo : rtInfos) {
                // walk through the map to determine the correct record type, this is done with the isAvailable() function
                if(rtInfo.getName() != 'Master' && rtInfo.isAvailable()) {
                    // below lines will only run one time only
                    System.debug('The RecordType :' +rtInfo.getName() + ' and the id: ' + rtInfo.getRecordTypeId() +' is available, adding it as parameter to the page.');
                    ApexPages.currentPage().getParameters().put('RecordType', rtInfo.getRecordTypeId());
                    ApexPages.currentPage().getParameters().put('RecordTypeName', rtInfo.getName());
                }
            }
            System.Debug('record type1'+ApexPages.currentPage().getParameters().get('RecordType'));
            if (ApexPages.currentPage().getParameters().get('RecordType') == null) {
                System.debug('Still null after for, this should never happen.');
            }
        }
    }
}